﻿/**
 * @file		dd_pmc_i2c.c
 * @brief		I2C driver
 * @note		None
 * @attention	None
 *
 * <B><I>Copyright 2016 Socionext Inc.</I></B>
 */

#include "dd_pmc_i2c.h"
#include "dd_arm.h"
#include "pmc.h"

/*----------------------------------------------------------------------*/
/* Definition															*/
/*----------------------------------------------------------------------*/
#define D_DD_PMC_I2C_10BIT_ADDRESS_FIX_BIT	(0xF0)
#define D_DD_PMC_I2C_DONT_CARE				(0)

#define D_DD_PMC_I2C_SCLFRQ_100K_50MHZ		(125)			// SCLFRQ value (100Kbps, PCLK=50MHz)
#define D_DD_PMC_I2C_SCLFRQ_400K_50MHZ		(32)			// SCLFRQ value (400Kbps, PCLK=50MHz)
#define D_DD_PMC_I2C_SCLFRQ_MAX				(127)			// SCLFRQ Max value (4 - 127)

//#define D_DD_I2C_DEBUG

/*----------------------------------------------------------------------*/
/* Enumeration															*/
/*----------------------------------------------------------------------*/
// I2C ST.MODE register code
typedef enum {
	E_DD_PMC_I2C_ST_MODE_IDLE		= 0x00,		// No mode Information Available
	E_DD_PMC_I2C_ST_MODE_STDONE		= 0x01,		// Start condition generated
	E_DD_PMC_I2C_ST_MODE_RSDONE		= 0x02,		// Repeated start condition generated
	E_DD_PMC_I2C_ST_MODE_IDLARL		= 0x03,		// Arbitrationlost, unaddressed slave mode entered
	E_DD_PMC_I2C_ST_MODE_MTADPA		= 0x04,		// Slave address sent, positive ACK
	E_DD_PMC_I2C_ST_MODE_MTADNA		= 0x05,		// Slave address sent, negative ACK
	E_DD_PMC_I2C_ST_MODE_MTDAPA		= 0x06,		// Data byte sent, positive ACK
	E_DD_PMC_I2C_ST_MODE_MTDANA		= 0x07,		// Data byte sent, negative ACK
	E_DD_PMC_I2C_ST_MODE_MRADPA		= 0x08,		// Slave address sent, positive ACK
	E_DD_PMC_I2C_ST_MODE_MRADNA		= 0x09,		// Slave address sent, negative ACK
	E_DD_PMC_I2C_ST_MODE_MRDAPA		= 0x0A,		// Data byte received, positive ACK
	E_DD_PMC_I2C_ST_MODE_MRDANA		= 0x0B,		// Data byte received, negative ACK
	E_DD_PMC_I2C_ST_MODE_SRADPA		= 0x10,		// Slave address received, positive ACK
	E_DD_PMC_I2C_ST_MODE_SRAAPA		= 0x11,		// Slave address received after arbitration loss, positive ACK
	E_DD_PMC_I2C_ST_MODE_SRDAPA		= 0x12,		// Data byte received, positive ACK
	E_DD_PMC_I2C_ST_MODE_SRDANA		= 0x13,		// Data byte received, negative ACK
	E_DD_PMC_I2C_ST_MODE_SSTOP		= 0x1C,		// Slave mode stop condition detected
	E_DD_PMC_I2C_ST_MODE_SGADPA		= 0x1D,		// Slave address received after arbitration loss, positive ACK
	E_DD_PMC_I2C_ST_MODE_SGAAPA		= 0x1E,		// Slave address received after arbitration loss, positive ACK
	E_DD_PMC_I2C_ST_MODE_BERROR		= 0x1F,		// Invalid start or stop condition detected
	E_DD_PMC_I2C_ST_MODE_STADPA		= 0x14,		// Slave address received, positive ACK
	E_DD_PMC_I2C_ST_MODE_STAAPA		= 0x15,		// Slave address received after arbitration loss, positive ACK
	E_DD_PMC_I2C_ST_MODE_STDAPA		= 0x16,		// Data byte received, positive ACK
	E_DD_PMC_I2C_ST_MODE_STDANA		= 0x17,		// Data byte received, negative ACK
	E_DD_PMC_I2C_ST_MODE_SATADP		= 0x18,		// Alart response address received, positive ACK
	E_DD_PMC_I2C_ST_MODE_SATAAP		= 0x19,		// Alart response address received after arbitration loss, positive ACK
	E_DD_PMC_I2C_ST_MODE_SATDAP		= 0x1A,		// Addressed With Alart response address, data byte send, positive ACK
	E_DD_PMC_I2C_ST_MODE_SATDAN		= 0x1B,		// Addressed With Alart response address, data byte send, negative ACK
#if 0	// Hs Mode
	E_DD_PMC_I2C_ST_MODE_MTMCER		= 0x0C,		// Master code transmitted error detected (pos. ACK)
	E_DD_PMC_I2C_ST_MODE_MTMCOK		= 0x21,		// Master code transmitted OK – switched to Hs mode
	E_DD_PMC_I2C_ST_MODE_HRSDONE	= 0x22,		// Repeated start condition generated
	E_DD_PMC_I2C_ST_MODE_HIDLARL	= 0x23,		// Arbitration lost, high-speed unaddressed slave mode enterd
	E_DD_PMC_I2C_ST_MODE_HMTADPA	= 0x24,		// Slave address sent, positive ACK
	E_DD_PMC_I2C_ST_MODE_HMTADNA	= 0x25,		// Slave address sent, negative ACK
	E_DD_PMC_I2C_ST_MODE_HMTDAPA	= 0x26,		// Data byte sent, positive ACK
	E_DD_PMC_I2C_ST_MODE_HMTDANA	= 0x27,		// Data byte sent, negative ACK
	E_DD_PMC_I2C_ST_MODE_HMRADPA	= 0x28,		// Slave address sent, positive ACK
	E_DD_PMC_I2C_ST_MODE_HMRADNA	= 0x29,		// Slave address sent, negative ACK
	E_DD_PMC_I2C_ST_MODE_HMRDAPA	= 0x2A,		// Data byte received, positive ACK
	E_DD_PMC_I2C_ST_MODE_HMRDANA	= 0x2B,		// Data byte received, negative ACK
	E_DD_PMC_I2C_ST_MODE_HSRADPA	= 0x30,		// Slave address received, positive ACK
	E_DD_PMC_I2C_ST_MODE_HSRDAPA	= 0x32,		// Data byte received, positive ACK
	E_DD_PMC_I2C_ST_MODE_HSRDANA	= 0x33,		// Data byte received, negative ACK
	E_DD_PMC_I2C_ST_MODE_HSTADTA	= 0x34,		// Slave address received, positive ACK
	E_DD_PMC_I2C_ST_MODE_HSTDAPA	= 0x36,		// Data byte send, positive ACK
	E_DD_PMC_I2C_ST_MODE_HSTDANA	= 0x37,		// Data byte send, negative ACK
#endif
} E_DD_PMC_I2C_ST_MODE;

// Communication Side
typedef enum {
	E_DD_PMC_I2C_SIDE_MASTER = 0,	// Master
	E_DD_PMC_I2C_SIDE_SLAVE			// Slave
} E_DD_PMC_I2C_SIDE;

// I2C Communication state
typedef enum {
	E_DD_PMC_I2C_STATE_IDLE = 0,			// IDLE
	E_DD_PMC_I2C_STATE_SENDING_DATA ,		// Sending Data
	E_DD_PMC_I2C_STATE_RECEIVING_DATA,		// Receiving data
	E_DD_PMC_I2C_STATE_SENDING_ADDRESS,		// Sending Address used on 10 bit address
	E_DD_PMC_I2C_STATE_END,					// Done normally
	E_DD_PMC_I2C_STATE_ERROR				// Error occurred
} E_DD_PMC_I2C_STATE;

// I2C Communication Event
typedef enum {
	E_DD_PMC_I2C_EVENT_START_READ = 0,		// Send START and read
	E_DD_PMC_I2C_EVENT_START_WRITE ,		// Send START and write
	E_DD_PMC_I2C_EVENT_SEND ,				// Send Address or Data
	E_DD_PMC_I2C_EVENT_RECEIVE ,			// Receive Data
	E_DD_PMC_I2C_EVENT_ERROR,				// Deal with error
	E_DD_PMC_I2C_EVENT_STOP,				// Send STOP
	E_DD_PMC_I2C_EVENT_SEND_PEC,			// Sending PEC byte
	E_DD_PMC_I2C_EVENT_END_RW				// End read or write
} E_DD_PMC_I2C_Event;

// I2C Communication Error information
typedef enum {
	E_DD_PMC_I2C_ERROR_NOT = 0,				// Error nothing
	E_DD_PMC_I2C_ERROR_BER ,				// Bus Error
	E_DD_PMC_I2C_ERROR_AL ,					// Arbitration lost
	E_DD_PMC_I2C_ERROR_COMM					// Communication error
} E_DD_PMC_I2C_ERROR;

// I2C Address counter
typedef enum {
	E_DD_PMC_I2C_ADDR_BYTE_1ST = 0,	// 7 bit address or first byte of 10 bit address
	E_DD_PMC_I2C_ADDR_BYTE_2ND ,		// second byte of 10 bit address
	E_DD_PMC_I2C_ADDR_BYTE_END		// End flag
} E_DD_PMC_I2C_ADDR_CNT;

/*----------------------------------------------------------------------*/
/* Structure															*/
/*----------------------------------------------------------------------*/
typedef union {
	UCHAR		addr_byte[E_DD_PMC_I2C_ADDR_BYTE_END];	// Used to access whole byte
	struct {
		UCHAR	rw				:1;		// 1: Read from slave	0:Write	to slave
		UCHAR	addr			:7;		// 7 bit slave address
		UCHAR					:8;		// reserve
	} bit;	// Used to 7 bit data
} U_DD_PMC_I2C_SLAVE_ADDR;

/*----------------------------------------------------------------------*/
/* Global Data															*/
/*----------------------------------------------------------------------*/
// I2C status
static volatile E_DD_PMC_I2C_STATE gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_IDLE;

// I2C event
static volatile E_DD_PMC_I2C_Event gDD_PMC_I2C_Next_Event = E_DD_PMC_I2C_EVENT_START_WRITE;

// I2C error
static volatile UINT32 gDD_PMC_I2C_Error = D_DDIM_OK;

// Side(Master or Slave) Information
static E_DD_PMC_I2C_SIDE gDD_PMC_I2C_Ctrl_Side = E_DD_PMC_I2C_SIDE_MASTER;

// Control data for Master
static T_DD_PMC_I2C_CTRL_MASTER gDD_PMC_I2C_Ctrl_Master;

// Control data for Slave
static T_DD_PMC_I2C_CTRL_SLAVE gDD_PMC_I2C_Ctrl_Slave;

// Start Information data
static T_DD_PMC_I2C_START_INFO gDD_PMC_I2C_Start_Info;

// Send or receive data pointer
static volatile UINT32 gDD_PMC_I2C_Data_Count = 0;

// Send or receive data pointer
static UCHAR* gDD_PMC_I2C_Data = NULL;

// Send or receive data num
static volatile UINT32 gDD_PMC_I2C_Data_Num = 0;

// Slave address
static U_DD_PMC_I2C_SLAVE_ADDR	gDD_PMC_I2C_Slave_Addr;

// PEC(Packet Error Checking) number of bytes
static volatile UINT32 gDD_PMC_I2C_PEC_Byte_Num = 0;

static volatile VP_PMC_I2C_CALLBACK	gDD_PMC_I2C_Callback = NULL;

/*----------------------------------------------------------------------*/
/* Macro																*/
/*----------------------------------------------------------------------*/
/* Nothing Special */

/*----------------------------------------------------------------------*/
/* Local Method Definition												*/
/*----------------------------------------------------------------------*/

/*----------------------------------------------------------------------*/
/* Local Function														*/
/*----------------------------------------------------------------------*/
// Get SCL frequency
static UCHAR dd_pmc_i2c_get_scl_frequency( E_DD_PMC_I2C_BPS bps )
{
	UCHAR sclfrq;		// fale safe

	// fix PCLK=50MHz.
	
	if( bps == E_DD_PMC_I2C_BPS_400 ){
		sclfrq = D_DD_PMC_I2C_SCLFRQ_400K_50MHZ;
	}
	else {
		sclfrq = D_DD_PMC_I2C_SCLFRQ_100K_50MHZ;
	}

	return sclfrq;
}

// Init PEC-info and Timeout error
static VOID dd_pmc_i2c_init_pec_info( VOID )
{
	// Init PEC info
	IO_PMC.I2C.CST.bit.PECFAULT = 0;
	IO_PMC.I2C.CST.bit.PECNEXT = 0;
}

// Init Timeout info
static VOID dd_pmc_i2c_init_timeout_info( VOID )
{
	IO_PMC.I2C.CST.bit.TOCDIV	= 0;
	IO_PMC.I2C.TOPR.bit.TOPR	= 0;
	IO_PMC.I2C.CST.bit.TERR		= 0;
}


/////////////////
///// Error /////
/////////////////
// Error occur process
static VOID dd_pmc_i2c_error_occur( VOID )
{
	T_DD_PMC_I2C_ACTION action;
	
	// Clear ST.INT (release SCK)
	IO_PMC.I2C.CTL1.bit.CLRST = 1;
	Dd_ARM_Dsb_Pou();

	if( gDD_PMC_I2C_Ctrl_Side == E_DD_PMC_I2C_SIDE_MASTER ){
		// Master
		IO_PMC.I2C.CTL1.bit.INTEN	= 0;
		
		// Error
		gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_ERROR;
		gDD_PMC_I2C_Next_Event = E_DD_PMC_I2C_EVENT_END_RW;

		if( gDD_PMC_I2C_Callback != NULL ){
			// Notify slave address specified to Callback function
			action = (*gDD_PMC_I2C_Callback)( E_DD_PMC_I2C_RECV_FROM_SLAVE_ERROR, gDD_PMC_I2C_Data_Count );

			switch( action.action_mode ){
				case D_DD_PMC_I2C_SEND_ACK_MASTER:
					// send ack
					IO_PMC.I2C.CTL1.bit.ACK = 0;
					break;
				case D_DD_PMC_I2C_SEND_NO_ACK_MASTER:
					// send no ack
					IO_PMC.I2C.CTL1.bit.ACK = 1;
					break;
				default:
					break;
			}
		}
	}
	else {
		// Slave
		gDD_PMC_I2C_Next_Event = E_DD_PMC_I2C_EVENT_ERROR;
		
		if( gDD_PMC_I2C_Callback != NULL ){
			(*gDD_PMC_I2C_Callback)( E_DD_PMC_I2C_RECV_FROM_MASTER_ERROR, D_DD_PMC_I2C_DONT_CARE );
		}
	}
}

// 0x03:Arbitrationlost, unaddressed slave mode entered
static VOID dd_pmc_i2c_st_mode_IDLARL_proc( VOID )
{
	gDD_PMC_I2C_Error = D_DD_PMC_I2C_ARBITRATION_LOST;

	dd_pmc_i2c_error_occur();
}

// 0x05:Slave address sent, negative ACK
static VOID dd_pmc_i2c_st_mode_MTADNA_proc( VOID )
{
	gDD_PMC_I2C_Error = D_DD_PMC_I2C_COMM_ERROR;

	dd_pmc_i2c_error_occur();
}

// 0x09:Slave address sent, negative ACK
static VOID dd_pmc_i2c_st_mode_MRADNA_proc( VOID )
{
	gDD_PMC_I2C_Error = D_DD_PMC_I2C_COMM_ERROR;

	dd_pmc_i2c_error_occur();
}

// 0x07:Data byte sent, negative ACK
static VOID dd_pmc_i2c_st_mode_MTDANA_proc( VOID )
{
	gDD_PMC_I2C_Error = D_DD_PMC_I2C_COMM_ERROR;

	dd_pmc_i2c_error_occur();
}

// 0x1F:Invalid start or stop condition detected
static VOID dd_pmc_i2c_st_mode_BERROR_proc()
{
	gDD_PMC_I2C_Error = D_DD_PMC_I2C_BUS_ERROR;

	dd_pmc_i2c_error_occur();
}

// Timeout Error
static VOID dd_pmc_i2c_st_mode_TERR_proc()
{
	gDD_PMC_I2C_Error = D_DD_PMC_I2C_TIMEOUT;

	dd_pmc_i2c_error_occur();
}


//////////////////////////////////
///// Master Start condition /////
//////////////////////////////////
// 0x01:Start condition generated
static VOID dd_pmc_i2c_st_mode_STDONE_proc( VOID )
{
	switch( gDD_PMC_I2C_Next_Event ){
		case E_DD_PMC_I2C_EVENT_START_READ:		// FALL THROUGH
		case E_DD_PMC_I2C_EVENT_START_WRITE:
			// Send slave address
			if( gDD_PMC_I2C_Ctrl_Master.dest_slave_addr_len == E_DD_PMC_I2C_ADDR_LEN_7 ){
				// 7 bit address
				IO_PMC.I2C.SDAT.word = gDD_PMC_I2C_Slave_Addr.addr_byte[E_DD_PMC_I2C_ADDR_BYTE_1ST];

				if(gDD_PMC_I2C_Next_Event == E_DD_PMC_I2C_EVENT_START_READ){
					// Read
					gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_RECEIVING_DATA;
					gDD_PMC_I2C_Next_Event = E_DD_PMC_I2C_EVENT_RECEIVE;
				}
				else{
					// Write
					gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_SENDING_DATA;
					gDD_PMC_I2C_Next_Event = E_DD_PMC_I2C_EVENT_SEND;
				}
			}
			else {	// E_DD_PMC_I2C_ADDR_LEN_10
				// 10 bit upper address
				IO_PMC.I2C.SDAT.word = ( gDD_PMC_I2C_Slave_Addr.addr_byte[E_DD_PMC_I2C_ADDR_BYTE_1ST] & 0xFE );
				gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_SENDING_ADDRESS;
			}

			// Clear ST.INT (release SCK)
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			break;

		default:
			// fail safe
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			IO_PMC.I2C.CTL1.bit.INTEN = 0;
			Dd_ARM_Dsb_Pou();
			break;
	}

	Dd_ARM_Dsb_Pou();
}

// 0x02:Repeated start condition generated
static VOID dd_pmc_i2c_st_mode_RSDONE_proc( VOID )
{
	switch(gDD_PMC_I2C_Next_Event){
		case E_DD_PMC_I2C_EVENT_START_READ:		// FALL THROUGH
		case E_DD_PMC_I2C_EVENT_START_WRITE:
			IO_PMC.I2C.SDAT.word = gDD_PMC_I2C_Slave_Addr.addr_byte[E_DD_PMC_I2C_ADDR_BYTE_1ST];

			if( gDD_PMC_I2C_Ctrl_Master.dest_slave_addr_len == E_DD_PMC_I2C_ADDR_LEN_7 ){
				// 7 bit address
				if( gDD_PMC_I2C_Next_Event == E_DD_PMC_I2C_EVENT_START_READ ){
					// Read
					gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_RECEIVING_DATA;
					gDD_PMC_I2C_Next_Event = E_DD_PMC_I2C_EVENT_RECEIVE;
				}
				else {
					// Write
					gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_SENDING_DATA;
					gDD_PMC_I2C_Next_Event = E_DD_PMC_I2C_EVENT_SEND;
				}
			}
			else {	// E_DD_PMC_I2C_ADDR_LEN_10
				// 10 bit address
				if( gDD_PMC_I2C_Next_Event == E_DD_PMC_I2C_EVENT_START_READ ){
					// Read
					gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_RECEIVING_DATA;
					gDD_PMC_I2C_Next_Event = E_DD_PMC_I2C_EVENT_RECEIVE;
				}
				else {
					// Write
					gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_SENDING_ADDRESS;
				}
			}

			// Clear ST.INT (release SCK)
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			break;

		default:
			// fail safe
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			IO_PMC.I2C.CTL1.bit.INTEN = 0;
			Dd_ARM_Dsb_Pou();
			break;
	}

	Dd_ARM_Dsb_Pou();
}

////////////////////////////////
///// Master Transmit Mode /////
////////////////////////////////
// Send data to slave
static VOID dd_pmc_i2c_send_data_to_slave( VOID )
{
	UCHAR* send_data;
	UINT32 send_count;

	send_data = gDD_PMC_I2C_Data;
	send_count = gDD_PMC_I2C_Data_Count;

	if( send_count < gDD_PMC_I2C_Data_Num ){
		// Start send
		IO_PMC.I2C.SDAT.word = send_data[send_count];
		send_count++;

		gDD_PMC_I2C_Data_Count = send_count;

		// Check end of send
		if( send_count == gDD_PMC_I2C_Data_Num ){
			// Check PEC enable
			if( (send_count + 1) == gDD_PMC_I2C_PEC_Byte_Num ){
				// Set PEC Next
				IO_PMC.I2C.CST.bit.PECNEXT = 1;
				Dd_ARM_Dsb_Pou();

				// Sending PEC byte
				gDD_PMC_I2C_Next_Event = E_DD_PMC_I2C_EVENT_SEND_PEC;
			}
			else {
				// End of send
				gDD_PMC_I2C_Next_Event = E_DD_PMC_I2C_EVENT_END_RW;
			}
		}

		// Clear ST.INT (release SCK)
		IO_PMC.I2C.CTL1.bit.CLRST = 1;
		Dd_ARM_Dsb_Pou();
	}
	else{
		;	// DO NOTHING
	}
}

// 0x04:Slave address sent, positive ACK
static VOID dd_pmc_i2c_st_mode_MTADPA_proc( VOID )
{
	switch( gDD_PMC_I2C_Next_Event ){
		case E_DD_PMC_I2C_EVENT_START_WRITE:
			// Send 10 bit lower address
			IO_PMC.I2C.SDAT.word = gDD_PMC_I2C_Slave_Addr.addr_byte[E_DD_PMC_I2C_ADDR_BYTE_2ND];
			Dd_ARM_Dsb_Pou();

			// Go to send data state
			gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_SENDING_DATA;
			gDD_PMC_I2C_Next_Event = E_DD_PMC_I2C_EVENT_SEND;

			// Clear ST.INT (release SCK)
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			Dd_ARM_Dsb_Pou();
			break;

		case E_DD_PMC_I2C_EVENT_SEND:
			// Send Data
			dd_pmc_i2c_send_data_to_slave();
			break;

		case E_DD_PMC_I2C_EVENT_SEND_PEC:
			// End of send
			gDD_PMC_I2C_Next_Event = E_DD_PMC_I2C_EVENT_END_RW;

			// Clear PEC Next
			IO_PMC.I2C.CST.bit.PECNEXT = 0;

			// Clear ST.INT (release SCK)
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			Dd_ARM_Dsb_Pou();
			break;

		case E_DD_PMC_I2C_EVENT_START_READ:
			// Send 10 bit lower address
			IO_PMC.I2C.SDAT.word = gDD_PMC_I2C_Slave_Addr.addr_byte[E_DD_PMC_I2C_ADDR_BYTE_2ND];
			Dd_ARM_Dsb_Pou();

			// Keep state
			gDD_PMC_I2C_Next_Event = E_DD_PMC_I2C_EVENT_RECEIVE;

			// Clear ST.INT (release SCK)
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			Dd_ARM_Dsb_Pou();
			break;

		case E_DD_PMC_I2C_EVENT_RECEIVE:
			// Resend 10 bit upper address and Read indicator
			IO_PMC.I2C.SDAT.word = gDD_PMC_I2C_Slave_Addr.addr_byte[E_DD_PMC_I2C_ADDR_BYTE_1ST];
			Dd_ARM_Dsb_Pou();

			// Set to receiving state
			gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_RECEIVING_DATA;

			// Generate the Restart condition
			IO_PMC.I2C.CTL1.bit.START	= 1;
			Dd_ARM_Dsb_Pou();

			// Clear ST.INT (release SCK)
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			Dd_ARM_Dsb_Pou();
			break;

		default:
			// fail safe
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			IO_PMC.I2C.CTL1.bit.INTEN = 0;
			Dd_ARM_Dsb_Pou();
			break;
	}
}

// 0x06:Data byte sent, positive ACK
static VOID dd_pmc_i2c_st_mode_MTDAPA_proc( VOID )
{
	if( gDD_PMC_I2C_State == E_DD_PMC_I2C_STATE_SENDING_DATA ){
		switch( gDD_PMC_I2C_Next_Event ){
			case E_DD_PMC_I2C_EVENT_SEND:
				// Send Data
				dd_pmc_i2c_send_data_to_slave();
				break;

			case E_DD_PMC_I2C_EVENT_END_RW:
				// End send
				IO_PMC.I2C.CTL1.bit.INTEN = 0;
				// Clear ST.INT (release SCK)
//				IO_PMC.I2C.CTL1.bit.CLRST = 1;		// Not clear for the Repeat Start Condition or Stop Condition
				Dd_ARM_Dsb_Pou();

				gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_END;

				if( gDD_PMC_I2C_Callback != NULL ){
					// Notify the end of transmission to Callback function.
					(*gDD_PMC_I2C_Callback)( 0, gDD_PMC_I2C_Data_Count);
				}
				
				break;

			default:
				// fail safe
				IO_PMC.I2C.CTL1.bit.CLRST = 1;
				IO_PMC.I2C.CTL1.bit.INTEN = 0;
				Dd_ARM_Dsb_Pou();
				break;
		}
	}
	else if( gDD_PMC_I2C_State == E_DD_PMC_I2C_STATE_SENDING_ADDRESS ){
		switch( gDD_PMC_I2C_Next_Event ){
			case E_DD_PMC_I2C_EVENT_RECEIVE:
				// Resend 10 bit upper address and Read indicator
				IO_PMC.I2C.SDAT.word = gDD_PMC_I2C_Slave_Addr.addr_byte[E_DD_PMC_I2C_ADDR_BYTE_1ST];
				Dd_ARM_Dsb_Pou();

				// Generate the Restart condition
				IO_PMC.I2C.CTL1.bit.START = 1;
				Dd_ARM_Dsb_Pou();

				// Clear ST.INT (release SCK)
				IO_PMC.I2C.CTL1.bit.CLRST = 1;
				Dd_ARM_Dsb_Pou();
				break;

			default:
				// fail safe
				IO_PMC.I2C.CTL1.bit.CLRST = 1;
				IO_PMC.I2C.CTL1.bit.INTEN = 0;
				Dd_ARM_Dsb_Pou();
				break;
		}
	}
}

///////////////////////////////
///// Master Receive Mode /////
///////////////////////////////
// Receive data from slave
static VOID dd_pmc_i2c_receive_data_from_slave( VOID )
{
	UCHAR* recv_data;
	UINT32 recv_count;

	recv_data = gDD_PMC_I2C_Data;
	recv_count = gDD_PMC_I2C_Data_Count;

	if( recv_count < gDD_PMC_I2C_Data_Num ){
		// Continue receive
		if( recv_count != 0 ){
			recv_data[recv_count-1] = (UCHAR)IO_PMC.I2C.SDAT.word;		// ToDo
		}
		recv_count++;
		gDD_PMC_I2C_Data_Count = recv_count;

		if( recv_count < gDD_PMC_I2C_Data_Num ){
			
			if( (recv_count + 1) == gDD_PMC_I2C_Data_Num ){
				// next receive data is last. send no ack
				IO_PMC.I2C.CTL1.bit.ACK = 1;
				
				// Check PEC enable
				if( recv_count == gDD_PMC_I2C_PEC_Byte_Num ){
					// Set PEC Next
					IO_PMC.I2C.CST.bit.PECNEXT = 1;
					Dd_ARM_Dsb_Pou();
				}
			}
			else {
				// send ack
				IO_PMC.I2C.CTL1.bit.ACK = 0;
			}
			
			// Clear ST.INT (release SCK)
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			Dd_ARM_Dsb_Pou();
		}
		else {
			// End of receive
			if ( gDD_PMC_I2C_Data_Count == (gDD_PMC_I2C_PEC_Byte_Num + 1) ){
				// Check PEC Fault Error
				if( IO_PMC.I2C.CST.bit.PECFAULT != 0 ){
					gDD_PMC_I2C_Error = D_DD_PMC_I2C_PEC_ERROR;
					dd_pmc_i2c_error_occur();
				}
			}
			else {
				gDD_PMC_I2C_Next_Event	= E_DD_PMC_I2C_EVENT_END_RW;
				gDD_PMC_I2C_State		= E_DD_PMC_I2C_STATE_END;
				
				IO_PMC.I2C.CTL1.bit.INTEN	= 0;	// Pause interrupt because INT has not been cleared
				Dd_ARM_Dsb_Pou();
				
				if( gDD_PMC_I2C_Callback != NULL ){
					// Notify slave address specified to Callback function
					(*gDD_PMC_I2C_Callback)( E_DD_PMC_I2C_RECV_FROM_SLAVE_NO_ACK, gDD_PMC_I2C_Data_Count );
				}
			}

			// Clear ST.INT (release SCK)
//			IO_PMC.I2C.CTL1.bit.CLRST = 1;		// Not clear for the Repeat Start Condition or Stop Condition
//			Dd_ARM_Dsb_Pou();
		}
	}
	else{
		;	// DO NOTHING
	}
}

// 0x08:Slave address sent, positive ACK
static VOID dd_pmc_i2c_st_mode_MRADPA_proc( VOID )
{
	switch( gDD_PMC_I2C_Next_Event ){
		case E_DD_PMC_I2C_EVENT_RECEIVE:
			// Receive Data
			dd_pmc_i2c_receive_data_from_slave();
			break;

		default:
			// fail safe
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			IO_PMC.I2C.CTL1.bit.INTEN	= 0;
			Dd_ARM_Dsb_Pou();
			break;
	}
}

// 0x0A:Data byte received, positive ACK
static VOID dd_pmc_i2c_st_mode_MRDAPA_proc( VOID )
{
	switch( gDD_PMC_I2C_Next_Event ){
		case E_DD_PMC_I2C_EVENT_RECEIVE:
			// Receive Data
			dd_pmc_i2c_receive_data_from_slave();
			break;

		default:
			// fail safe
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			IO_PMC.I2C.CTL1.bit.INTEN	= 0;
			Dd_ARM_Dsb_Pou();
			break;
	}
}

// 0x0B:Data byte received, negative ACK
static VOID dd_pmc_i2c_st_mode_MRDANA_proc( VOID )
{
	switch( gDD_PMC_I2C_Next_Event ){
		case E_DD_PMC_I2C_EVENT_RECEIVE:
			// Receive Data
			dd_pmc_i2c_receive_data_from_slave();
			break;

		case E_DD_PMC_I2C_EVENT_END_RW:
			// End receive
			gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_END;

			// Clear ST.INT (release SCK)
//			IO_PMC.I2C.CTL1.bit.CLRST = 1;		// Not clear for the Repeat Start Condition or Stop Condition
//			Dd_ARM_Dsb_Pou();
			break;

		default:
			// fail safe
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			IO_PMC.I2C.CTL1.bit.INTEN	= 0;
			Dd_ARM_Dsb_Pou();
			break;
	}
}

//////////////////////////////
///// Slave Receive Mode /////
//////////////////////////////
// Notify slave address specified
static VOID dd_pmc_i2c_notify_slave_address_specified( VOID )
{
	if( gDD_PMC_I2C_Callback != NULL ){

		// Notify slave address specified to Callback function
		(*gDD_PMC_I2C_Callback)( E_DD_PMC_I2C_RECV_FROM_MASTER_ADDRESS, (UCHAR)IO_PMC.I2C.ADDR.word );
	}

	// Clear ST.INT (release SCK)
	IO_PMC.I2C.CTL1.bit.CLRST = 1;
	Dd_ARM_Dsb_Pou();
}

// 0x10:Slave address received, positive ACK
static VOID dd_pmc_i2c_st_mode_SRADPA_proc( VOID )
{
	dd_pmc_i2c_notify_slave_address_specified();
}

// 0x11:Slave address received after arbitration loss, positive ACK
static VOID dd_pmc_i2c_st_mode_SRAAPA_proc( VOID )
{
	dd_pmc_i2c_notify_slave_address_specified();
}

static VOID dd_pmc_i2c_receive_data_from_master()
{
	T_DD_PMC_I2C_ACTION	action;
	E_DD_PMC_I2C_RECV	receive_sig = E_DD_PMC_I2C_RECV_FROM_MASTER_DATA;

	if( gDD_PMC_I2C_Callback != NULL ){
		gDD_PMC_I2C_Data_Count++;

		// Check PEC enable
		if( gDD_PMC_I2C_Data_Count == gDD_PMC_I2C_PEC_Byte_Num ){
			// Set PEC Next
			IO_PMC.I2C.CST.bit.PECNEXT = 1;
			Dd_ARM_Dsb_Pou();
		}
		else if ( gDD_PMC_I2C_Data_Count == (gDD_PMC_I2C_PEC_Byte_Num + 1) ){
			// Check PEC Fault Error
			if( IO_PMC.I2C.CST.bit.PECFAULT != 0 ){
				receive_sig = E_DD_PMC_I2C_RECV_FROM_MASTER_ERROR;
				gDD_PMC_I2C_Error = D_DD_PMC_I2C_PEC_ERROR;
			}
		}

		// Receive data from master
		action = (*gDD_PMC_I2C_Callback)( receive_sig, (UCHAR)IO_PMC.I2C.SDAT.word );

		switch( action.action_mode ){
			case D_DD_PMC_I2C_SEND_ACK_MASTER:
				// Continue receive data
				IO_PMC.I2C.CTL1.bit.ACK = 0;
				break;
			case D_DD_PMC_I2C_SEND_NO_ACK_MASTER:
				// End receive data
				IO_PMC.I2C.CTL1.bit.ACK = 1;
				break;
			default:
				break;
		}
	}

	// Clear ST.INT (release SCK)
	IO_PMC.I2C.CTL1.bit.CLRST = 1;
	Dd_ARM_Dsb_Pou();
}

// 0x12:Data byte received, positive ACK
static VOID dd_pmc_i2c_st_mode_SRDAPA_proc( VOID )
{
	dd_pmc_i2c_receive_data_from_master();
}

// 0x13:Data byte received, negative ACK
static VOID dd_pmc_i2c_st_mode_SRDANA_proc( VOID )
{
	// Clear ST.INT (release SCK)
	IO_PMC.I2C.CTL1.bit.CLRST = 1;
	Dd_ARM_Dsb_Pou();
}

// 0x1C:Slave mode stop condition detected
static VOID dd_pmc_i2c_st_mode_SSTOP_proc( VOID )
{
	// Clear ST.INT (release SCK)
	IO_PMC.I2C.CTL1.bit.CLRST = 1;
	Dd_ARM_Dsb_Pou();
}

// 0x1D:Slave address received after arbitration loss, positive ACK
static VOID dd_pmc_i2c_st_mode_SGADPA_proc( VOID )
{
	dd_pmc_i2c_notify_slave_address_specified();
}

// 0x1E:Slave address received after arbitration loss, positive ACK
static VOID dd_pmc_i2c_st_mode_SGAAPA_proc( VOID )
{
	dd_pmc_i2c_notify_slave_address_specified();
}

///////////////////////////////
///// Slave Transmit Mode /////
///////////////////////////////
// Send data to master
static VOID dd_pmc_i2c_send_data_to_master( VOID )
{
	T_DD_PMC_I2C_ACTION action;

	if( gDD_PMC_I2C_Callback != NULL ){
		// Detect ACK
		// Send data to master
		action = (*gDD_PMC_I2C_Callback)( E_DD_PMC_I2C_RECV_FROM_MASTER_ACK, D_DD_PMC_I2C_DONT_CARE );

		if( action.action_mode == D_DD_PMC_I2C_SEND_DATA_2_MASTER ){
			// Send data
			IO_PMC.I2C.SDAT.word = action.send_data;
			Dd_ARM_Dsb_Pou();

			gDD_PMC_I2C_Data_Count++;

			if( gDD_PMC_I2C_Data_Count == gDD_PMC_I2C_PEC_Byte_Num ){
				// Set PEC Next
				IO_PMC.I2C.CST.bit.PECNEXT = 1;
				Dd_ARM_Dsb_Pou();
			}
		}
		else{
			// Error
			Ddim_Print(("I2C Slave Action Mode is invalid!! action_mode = %d\n", action.action_mode));
		}
	}

	// Clear ST.INT (release SCK)
	IO_PMC.I2C.CTL1.bit.CLRST = 1;
	Dd_ARM_Dsb_Pou();
}

// 0x14:Slave address received, positive ACK
static VOID dd_pmc_i2c_st_mode_STADPA_proc( VOID )
{
	dd_pmc_i2c_init_pec_info();

	dd_pmc_i2c_send_data_to_master();
}

// 0x15:Slave address received after arbitration loss, positive ACK
static VOID dd_pmc_i2c_st_mode_STAAPA_proc( VOID )
{
	dd_pmc_i2c_init_pec_info();

	dd_pmc_i2c_send_data_to_master();
}

// 0x16:Data byte received, positive ACK
static VOID dd_pmc_i2c_st_mode_STDAPA_proc( VOID )
{
	dd_pmc_i2c_send_data_to_master();
}

// 0x17:Data byte received, negative ACK
static VOID dd_pmc_i2c_st_mode_STDANA_proc()
{
	if( gDD_PMC_I2C_Callback != NULL ){
		// No detect ACK
		(*gDD_PMC_I2C_Callback)( E_DD_PMC_I2C_RECV_FROM_MASTER_NO_ACK, D_DD_PMC_I2C_DONT_CARE );
	}

	// Clear ST.INT (release SCK)
	IO_PMC.I2C.CTL1.bit.CLRST = 1;
	Dd_ARM_Dsb_Pou();
}

// 0x18:Alart response address received, positive ACK
static VOID dd_pmc_i2c_st_mode_SATADP_proc( VOID )
{
	dd_pmc_i2c_init_pec_info();

	dd_pmc_i2c_send_data_to_master();
}

// 0x19:Alart response address received after arbitration loss, positive ACK
static VOID dd_pmc_i2c_st_mode_SATAAP_proc( VOID )
{
	dd_pmc_i2c_init_pec_info();

	dd_pmc_i2c_send_data_to_master();
}

// 0x1A:Addressed With Alart response address, data byte send, positive ACK
static VOID dd_pmc_i2c_st_mode_SATDAP_proc( VOID )
{
	dd_pmc_i2c_send_data_to_master();
}

// 0x1B:Addressed With Alart response address, data byte send, negative ACK
static VOID dd_pmc_i2c_st_mode_SATDAN_proc( VOID )
{
	if( gDD_PMC_I2C_Callback != NULL ){
		// No detect ACK
		(*gDD_PMC_I2C_Callback)( E_DD_PMC_I2C_RECV_FROM_MASTER_NO_ACK, D_DD_PMC_I2C_DONT_CARE );
	}

	// Clear ST.INT (release SCK)
	IO_PMC.I2C.CTL1.bit.CLRST = 1;
	Dd_ARM_Dsb_Pou();
}

/*----------------------------------------------------------------------*/
/* Global Function														*/
/*----------------------------------------------------------------------*/
// Set I2C Master Control information
INT32 Dd_PMC_I2C_Ctrl_Master( const T_DD_PMC_I2C_CTRL_MASTER* const ctrl_master )
{
#ifdef CO_PARAM_CHECK
	if( ctrl_master == NULL ){
		Ddim_Assertion(("Dd_PMC_I2C_Ctrl_Master() error. ctrl_master is NULL.\n"));
		return D_DD_PMC_I2C_INPUT_PARAM_ERROR;
	}
#endif

	gDD_PMC_I2C_Ctrl_Master = *ctrl_master; 

	// Enable I2C
	IO_PMC.I2C.CTL2.bit.ENABLE = 1;

	// Set SCL Frequency
	IO_PMC.I2C.CTL2.bit.SCLFRQ = dd_pmc_i2c_get_scl_frequency( ctrl_master->bps );

	// Set Slave Address Enable
	IO_PMC.I2C.ADDR.bit.SAEN = 0;

	// Set Global Call Match Enable
	IO_PMC.I2C.CTL1.bit.GCMEN	= 0;

	// Set Alert Response Match Enable
	IO_PMC.I2C.CTL1.bit.SMBARE	= 0;

	// Init PEC-info
	dd_pmc_i2c_init_pec_info();

	// Init Timeout info
	dd_pmc_i2c_init_timeout_info();

	Dd_ARM_Dsb_Pou();

	gDD_PMC_I2C_Ctrl_Side = E_DD_PMC_I2C_SIDE_MASTER;

	return D_DDIM_OK;
}

// Get I2C Master Control information
INT32 Dd_PMC_I2C_Get_Ctrl_Master( T_DD_PMC_I2C_CTRL_MASTER* const ctrl_master )
{
#ifdef CO_PARAM_CHECK
	if( ctrl_master == NULL ){
		Ddim_Assertion(("Dd_PMC_I2C_Get_Ctrl_Master() error. ctrl_master is NULL.\n"));
		return D_DD_PMC_I2C_INPUT_PARAM_ERROR;
	}
#endif

	*ctrl_master = gDD_PMC_I2C_Ctrl_Master;

	return D_DDIM_OK;
}

// Set I2C Slave Control information
INT32 Dd_PMC_I2C_Ctrl_Slave( const T_DD_PMC_I2C_CTRL_SLAVE* const ctrl_slave )
{
#ifdef CO_PARAM_CHECK
	if( ctrl_slave == NULL ){
		Ddim_Assertion(("Dd_PMC_I2C_Ctrl_Slave() error. ctrl_slave is NULL.\n"));
		return D_DD_PMC_I2C_INPUT_PARAM_ERROR;
	}
#endif

	gDD_PMC_I2C_Ctrl_Slave = *ctrl_slave; 

	// Enable I2C
	IO_PMC.I2C.CTL2.bit.ENABLE = 1;

	// Set Own Slave Address
	if( ctrl_slave->own_slave_addr_len == E_DD_PMC_I2C_ADDR_LEN_7 ){
		IO_PMC.I2C.CTL3.bit.S10EN	= 0;
		IO_PMC.I2C.ADDR.bit.ADDR	= ctrl_slave->own_slave_addr;
	}
	else {	// E_DD_PMC_I2C_ADDR_LEN_10
		IO_PMC.I2C.CTL3.bit.S10EN	= 1;
		IO_PMC.I2C.ADDR.bit.ADDR	= ctrl_slave->own_slave_addr & 0x7F;
		IO_PMC.I2C.CTL3.bit.S10ADR	= (ctrl_slave->own_slave_addr >>  7) & 0x07;
	}

	// Set Slave Address Enable
	IO_PMC.I2C.ADDR.bit.SAEN = 1;

	// Set Global Call Match Enable
	IO_PMC.I2C.CTL1.bit.GCMEN	= ctrl_slave->global_call_en;

	// Set Alert Response Match Enable
	IO_PMC.I2C.CTL1.bit.SMBARE	= 0;

	// Init PEC-info and Timeout error
	dd_pmc_i2c_init_pec_info();

	// Init Timeout info
	dd_pmc_i2c_init_timeout_info();

	Dd_ARM_Dsb_Pou();

	gDD_PMC_I2C_Ctrl_Side = E_DD_PMC_I2C_SIDE_SLAVE;

	return D_DDIM_OK;
}

// Get I2C Slave Control information
INT32 Dd_PMC_I2C_Get_Ctrl_Slave( T_DD_PMC_I2C_CTRL_SLAVE* const ctrl_slave )
{
#ifdef CO_PARAM_CHECK
	if( ctrl_slave == NULL ){
		Ddim_Assertion(("Dd_PMC_I2C_Get_Ctrl_Slave() error. ctrl_slave is NULL.\n"));
		return D_DD_PMC_I2C_INPUT_PARAM_ERROR;
	}
#endif

	*ctrl_slave = gDD_PMC_I2C_Ctrl_Slave;

	return D_DDIM_OK;
}

// Set Control information for SMBus.
INT32 Dd_PMC_I2C_Ctrl_SMBus( const T_DD_PMC_I2C_CTRL_SMBUS* const ctrl_smbus )
{
#ifdef CO_PARAM_CHECK
	if( ctrl_smbus == NULL ){
		Ddim_Assertion(("Dd_PMC_I2C_Ctrl_SMBus() error. ctrl_smbus is NULL.\n"));
		return D_DD_PMC_I2C_INPUT_PARAM_ERROR;
	}
#endif

	if( IO_PMC.I2C.CTL2.bit.ENABLE != 1 ){
		// State error
		return D_DD_PMC_I2C_STATUS_ABNORMAL;
	}

	// Set Alert Response Match Enable (Slave only)
	IO_PMC.I2C.CTL1.bit.SMBARE	= ctrl_smbus->alert_resp_en;

	// Set PEC(Packet Error Checking) number of bytes.
	gDD_PMC_I2C_PEC_Byte_Num		= ctrl_smbus->pec_num;

	// Set Timeout Divider & Prescaler
	IO_PMC.I2C.CST.bit.TOCDIV	= ctrl_smbus->timeout_div;
	IO_PMC.I2C.TOPR.bit.TOPR	= ctrl_smbus->timeout_presc;
	IO_PMC.I2C.CST.bit.TERR	= 0;

	Dd_ARM_Dsb_Pou();

	return D_DDIM_OK;
}

// Get Control information for SMBus.
INT32 Dd_PMC_I2C_Get_Ctrl_SMBus( T_DD_PMC_I2C_CTRL_SMBUS* const ctrl_smbus )
{
#ifdef CO_PARAM_CHECK
	if( ctrl_smbus == NULL ){
		Ddim_Assertion(("Dd_PMC_I2C_Get_Ctrl_SMBus() error. ctrl_smbus is NULL.\n"));
		return D_DD_PMC_I2C_INPUT_PARAM_ERROR;
	}
#endif

	if( IO_PMC.I2C.CTL2.bit.ENABLE != 1 ){
		// State error
		return D_DD_PMC_I2C_STATUS_ABNORMAL;
	}

	// Get Alert Response Match Enable (Slave only)
	ctrl_smbus->alert_resp_en	= IO_PMC.I2C.CTL1.bit.SMBARE;

	// Get PEC(Packet Error Checking) number of bytes.
	ctrl_smbus->pec_num			= gDD_PMC_I2C_PEC_Byte_Num;

	// Get Timeout Divider & Prescaler
	ctrl_smbus->timeout_div		= (E_DD_PMC_I2C_TO_DIV)IO_PMC.I2C.CST.bit.TOCDIV;
	ctrl_smbus->timeout_presc	= IO_PMC.I2C.TOPR.bit.TOPR;

	return D_DDIM_OK;
}

// Send start condition.
INT32 Dd_PMC_I2C_Start_Master( const T_DD_PMC_I2C_START_INFO* const start_info, VP_PMC_I2C_CALLBACK callback )
{
	INT32 ret = D_DDIM_OK;
	INT32 wait;

#ifdef CO_PARAM_CHECK
	if( start_info == NULL ){
		Ddim_Assertion(("Dd_PMC_I2C_Start_Master() error. start_info is NULL.\n"));
		return D_DD_PMC_I2C_INPUT_PARAM_ERROR;
	}
#endif

	if( gDD_PMC_I2C_Ctrl_Side != E_DD_PMC_I2C_SIDE_MASTER ){
		// State error
		return D_DD_PMC_I2C_STATUS_ABNORMAL;
	}

	if( gDD_PMC_I2C_State == E_DD_PMC_I2C_STATE_IDLE ){
		if( IO_PMC.I2C.CST.bit.BB == 1 ){
			// Bus Busy error
			return D_DD_PMC_I2C_STATUS_ABNORMAL;
		}
	}
	
	if (callback != NULL) {
		gDD_PMC_I2C_Callback = callback;
	}
	
	switch( gDD_PMC_I2C_State ){
		case E_DD_PMC_I2C_STATE_IDLE:	// FALL THROUGH
		case E_DD_PMC_I2C_STATE_END:
			gDD_PMC_I2C_Start_Info = *start_info;

			// Set destination slave address
			if( gDD_PMC_I2C_Ctrl_Master.dest_slave_addr_len == E_DD_PMC_I2C_ADDR_LEN_7 ){
				gDD_PMC_I2C_Slave_Addr.bit.addr = (UCHAR)gDD_PMC_I2C_Ctrl_Master.dest_slave_addr;
			}
			else {	// E_DD_PMC_I2C_ADDR_LEN_10
				gDD_PMC_I2C_Slave_Addr.bit.addr = ((gDD_PMC_I2C_Ctrl_Master.dest_slave_addr >> 8) & 0x03);
				gDD_PMC_I2C_Slave_Addr.addr_byte[E_DD_PMC_I2C_ADDR_BYTE_1ST] |= D_DD_PMC_I2C_10BIT_ADDRESS_FIX_BIT;
				gDD_PMC_I2C_Slave_Addr.addr_byte[E_DD_PMC_I2C_ADDR_BYTE_2ND] = (gDD_PMC_I2C_Ctrl_Master.dest_slave_addr & 0xFF);
			}

			if( start_info->rw_mode == E_DD_PMC_I2C_RW_MODE_READ ){
				// read mode
				gDD_PMC_I2C_Slave_Addr.bit.rw	= 1;
				gDD_PMC_I2C_Data_Num			= start_info->rw_data_len + 1;
				gDD_PMC_I2C_Next_Event			= E_DD_PMC_I2C_EVENT_START_READ;
			}
			else {
				// write mode
				gDD_PMC_I2C_Slave_Addr.bit.rw	= 0;
				gDD_PMC_I2C_Data_Num			= start_info->rw_data_len;
				gDD_PMC_I2C_Next_Event			= E_DD_PMC_I2C_EVENT_START_WRITE;
			}

			gDD_PMC_I2C_Data			= start_info->rw_data;
			gDD_PMC_I2C_Data_Count		= 0;
			gDD_PMC_I2C_Error			= D_DDIM_OK;

			// Init PEC-info and Timeout error
			dd_pmc_i2c_init_pec_info();

			// Generate the Start Condition
			IO_PMC.I2C.CTL1.bit.START	= 1;
			Dd_ARM_Dsb_Pou();

			if( gDD_PMC_I2C_State == E_DD_PMC_I2C_STATE_END ){
				// Clear ST.INT (release SCK)
				IO_PMC.I2C.CTL1.bit.CLRST = 1;		// Clear interrupt for the Repeat Start Condition or Stop Condition
				Dd_ARM_Dsb_Pou();
			}
			
			// wait START bit clear (Start condition send)
			for ( wait = 0; wait < 1000; wait++ ){
				if( IO_PMC.I2C.CTL1.bit.START == 0 ){
					break;
				}
			}
			
			// Set Interrupt Enable
			IO_PMC.I2C.CTL1.bit.INTEN	= 1;
			
			break;
			
		default:
			// State error
			ret = D_DD_PMC_I2C_STATUS_ABNORMAL;
			break;
	}

	return ret;
}

// Send stop condition.
INT32 Dd_PMC_I2C_Stop_Master( VOID )
{
	INT32 ret = D_DDIM_OK;
	INT32 wait;

	switch(gDD_PMC_I2C_State){
		case E_DD_PMC_I2C_STATE_END:
			gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_IDLE;

			// Generate the Stop Condition
			IO_PMC.I2C.CTL1.bit.STOP = 1;

			// Clear ST.INT (release SCK)
			IO_PMC.I2C.CTL1.bit.CLRST = 1;		// Clear interrupt for the Repeat Start Condition or Stop Condition

			// Set Interrupt Disable
			IO_PMC.I2C.CTL1.bit.INTEN	= 0;
			Dd_ARM_Dsb_Pou();

			for( wait = 0; wait < 1000; wait++ ){
				if( IO_PMC.I2C.CST.bit.BB == 0 ){
					break;
				}
			}

			break;

		default:
			ret = D_DD_PMC_I2C_STATUS_ABNORMAL;
			break;
	}

	return ret;
}

// Master force stop.
VOID Dd_PMC_I2C_Force_Stop_Master( VOID )
{
	switch( gDD_PMC_I2C_State ){
		case E_DD_PMC_I2C_STATE_SENDING_DATA:		// Sending Data. FALL THROUGH
		case E_DD_PMC_I2C_STATE_RECEIVING_DATA:		// Receiving data. FALL THROUGH
		case E_DD_PMC_I2C_STATE_SENDING_ADDRESS:	// Sending Address used on 10 bit address. FALL THROUGH
			//Communication state
			dd_pmc_i2c_error_occur();
			break;
			break;

		default:
			break;
	}
}

// Start the communication waiting from the master.
INT32 Dd_PMC_I2C_Start_Slave( VP_PMC_I2C_CALLBACK callback  )
{
	INT32 ret = D_DDIM_OK;

	if( gDD_PMC_I2C_Ctrl_Side != E_DD_PMC_I2C_SIDE_SLAVE ){
		// State error
		return D_DD_PMC_I2C_STATUS_ABNORMAL;
	}

	if (callback != NULL) {
		gDD_PMC_I2C_Callback = callback;
	}
	
	gDD_PMC_I2C_Data_Count		= 0;
	gDD_PMC_I2C_Error			= D_DDIM_OK;

	// Set Interrupt Enable
	IO_PMC.I2C.CTL1.bit.INTEN	= 1;
	Dd_ARM_Dsb_Pou();

	return ret;
}

// Stop thje communication waiting from the master.
VOID Dd_PMC_I2C_Stop_Slave( VOID )
{
	// Set Interrupt Disable
	IO_PMC.I2C.CTL1.bit.INTEN	= 0;
	Dd_ARM_Dsb_Pou();
}

// To terminate the I2C.
VOID Dd_PMC_I2C_Terminate( VOID )
{
	// State:IDLE
	gDD_PMC_I2C_State = E_DD_PMC_I2C_STATE_IDLE;

	// Clear EN.
	IO_PMC.I2C.CTL2.bit.ENABLE = 0;
	
	Dd_ARM_Dsb_Pou();
}

// Set Toggle SCL.
VOID Dd_PMC_I2C_Set_Toggle_SCL( VOID )
{
	IO_PMC.I2C.CST.bit.TGSCL = 1;
	Dd_ARM_Dsb_Pou();
}

// Get Test SDA.
INT32 Dd_PMC_I2C_Get_Test_SDA( UCHAR* sda )
{
	INT32 ret = D_DDIM_OK;

#ifdef CO_PARAM_CHECK
	if( sda == NULL ){
		Ddim_Assertion(("Dd_PMC_I2C_Get_Test_SDA() error. sda is NULL.\n"));
		return D_DD_PMC_I2C_INPUT_PARAM_ERROR;
	}
#endif

	*sda = IO_PMC.I2C.CST.bit.TSDA;

	return ret;
}

// Get Error Cause.
UINT32 Dd_PMC_I2C_Get_Error_Cause( VOID )
{
	return gDD_PMC_I2C_Error;
}

// Interrupt handler.
VOID Dd_PMC_I2C_Int_Handler( VOID )
{
	if( IO_PMC.I2C.CST.bit.TERR == 1 ){
		// Timeout Error
		dd_pmc_i2c_st_mode_TERR_proc();
	}

#ifdef D_DD_I2C_DEBUG
	printf("IO_PMC.I2C.ST.bit.MODE=0x%02X, gDD_PMC_I2C_State=%d, gDD_PMC_I2C_Next_Event=%d\n",
		IO_PMC.I2C.ST.bit.MODE, gDD_PMC_I2C_State, gDD_PMC_I2C_Next_Event);
#endif	// D_DD_I2C_DEBUG

	switch( IO_PMC.I2C.ST.bit.MODE ){
		//////////////////////////////////
		///// Master Start condition /////
		//////////////////////////////////
		case E_DD_PMC_I2C_ST_MODE_STDONE:		// 0x01:Start condition generated
			dd_pmc_i2c_st_mode_STDONE_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_RSDONE:		// 0x02:Repeated start condition generated
			dd_pmc_i2c_st_mode_RSDONE_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_IDLARL:		// 0x03:Arbitrationlost, unaddressed slave mode entered
			dd_pmc_i2c_st_mode_IDLARL_proc();
			break;

		////////////////////////////////
		///// Master Transmit Mode /////
		////////////////////////////////
		case E_DD_PMC_I2C_ST_MODE_MTADPA:		// 0x04:Slave address sent, positive ACK
			dd_pmc_i2c_st_mode_MTADPA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_MTADNA:		// 0x05:Slave address sent, negative ACK
			dd_pmc_i2c_st_mode_MTADNA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_MTDAPA:		// 0x06:Data byte sent, positive ACK
			dd_pmc_i2c_st_mode_MTDAPA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_MTDANA:		// 0x07:Data byte sent, negative ACK
			dd_pmc_i2c_st_mode_MTDANA_proc();
			break;

		///////////////////////////////
		///// Master Receive Mode /////
		///////////////////////////////
		case E_DD_PMC_I2C_ST_MODE_MRADPA:		// 0x08:Slave address sent, positive ACK
			dd_pmc_i2c_st_mode_MRADPA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_MRADNA:		// 0x09:Slave address sent, negative ACK
			dd_pmc_i2c_st_mode_MRADNA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_MRDAPA:		// 0x0A:Data byte received, positive ACK
			dd_pmc_i2c_st_mode_MRDAPA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_MRDANA:		// 0x0B:Data byte received, negative ACK
			dd_pmc_i2c_st_mode_MRDANA_proc();
			break;

		//////////////////////////////
		///// Slave Receive Mode /////
		//////////////////////////////
		case E_DD_PMC_I2C_ST_MODE_SRADPA:		// 0x10:Slave address received, positive ACK
			dd_pmc_i2c_st_mode_SRADPA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_SRAAPA:		// 0x11:Slave address received after arbitration loss, positive ACK
			dd_pmc_i2c_st_mode_SRAAPA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_SRDAPA:		// 0x12:Data byte received, positive ACK
			dd_pmc_i2c_st_mode_SRDAPA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_SRDANA:		// 0x13:Data byte received, negative ACK
			dd_pmc_i2c_st_mode_SRDANA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_SSTOP:		// 0x1C:Slave mode stop condition detected
			dd_pmc_i2c_st_mode_SSTOP_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_SGADPA:		// 0x1D:Slave address received after arbitration loss, positive ACK
			dd_pmc_i2c_st_mode_SGADPA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_SGAAPA:		// 0x1E:Slave address received after arbitration loss, positive ACK
			dd_pmc_i2c_st_mode_SGAAPA_proc();
			break;

		///////////////////////////////
		///// Slave Transmit Mode /////
		///////////////////////////////
		case E_DD_PMC_I2C_ST_MODE_STADPA:		// 0x14:Slave address received, positive ACK
			dd_pmc_i2c_st_mode_STADPA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_STAAPA:		// 0x15:Slave address received after arbitration loss, positive ACK
			dd_pmc_i2c_st_mode_STAAPA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_STDAPA:		// 0x16:Data byte received, positive ACK
			dd_pmc_i2c_st_mode_STDAPA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_STDANA:		// 0x17:Data byte received, negative ACK
			dd_pmc_i2c_st_mode_STDANA_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_SATADP:		// 0x18:Alart response address received, positive ACK
			dd_pmc_i2c_st_mode_SATADP_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_SATAAP:		// 0x19:Alart response address received after arbitration loss, positive ACK
			dd_pmc_i2c_st_mode_SATAAP_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_SATDAP:		// 0x1A:Addressed With Alart response address, data byte send, positive ACK
			dd_pmc_i2c_st_mode_SATDAP_proc();
			break;
		case E_DD_PMC_I2C_ST_MODE_SATDAN:		// 0x1B:Addressed With Alart response address, data byte send, negative ACK
			dd_pmc_i2c_st_mode_SATDAN_proc();
			break;

		/////////////////
		///// Error /////
		/////////////////
		case E_DD_PMC_I2C_ST_MODE_BERROR:		// 0x1F:Invalid start or stop condition detected
			dd_pmc_i2c_st_mode_BERROR_proc();
			break;
		default:
			IO_PMC.I2C.CTL1.bit.CLRST = 1;
			IO_PMC.I2C.CTL1.bit.INTEN = 0;
			Dd_ARM_Dsb_Pou();
			break;
	}
}

#ifdef CO_DDIM_UTILITY_USE
//---------------------- utility section -------------------------------
// Set SCL Frequency
INT32 Dd_PMC_I2C_Set_SCL( UCHAR scl )
{
#ifdef CO_PARAM_CHECK
	if( scl > D_DD_PMC_I2C_SCLFRQ_MAX ){
		Ddim_Assertion(("Dd_PMC_I2C_Set_SCL() error.  scl is abnormal.\n"));
		return D_DD_PMC_I2C_INPUT_PARAM_ERROR;
	}
#endif

	// Set SCL Frequency
	IO_PMC.I2C.CTL2.bit.SCLFRQ = scl;
	Dd_ARM_Dsb_Pou();

	return D_DDIM_OK;
}

// Get SCL Frequency
INT32 Dd_PMC_I2C_Get_SCL( UCHAR* scl )
{
#ifdef CO_PARAM_CHECK
	if( scl == NULL ){
		Ddim_Assertion(("Dd_PMC_I2C_Get_SCL() error. scl is NULL.\n"));
		return D_DD_PMC_I2C_INPUT_PARAM_ERROR;
	}
#endif

	// Get SCL Frequency
	*scl = IO_PMC.I2C.CTL2.bit.SCLFRQ;

	return D_DDIM_OK;
}
#endif

// aDvfs =============================---------------------------
T_DD_PMC_ADVFS_DATA G_advfs ={0};
UCHAR  G_advfs_en = 0;

int Dd_PMC_ADVFS_Set_EN(const UCHAR en)
{
	G_advfs_en = en;
	//printf("G_advfs_en = %x\n", G_advfs_en);
	return D_DDIM_OK;
}
int Dd_PMC_ADVFS_Set_Avs(const UCHAR avs)
{
	G_advfs.AVS = avs;
	//printf("G_advfs.AVS = %x\n", G_advfs.AVS);
	return D_DDIM_OK;
}
int Dd_PMC_ADVFS_Set_Dvfs(const UCHAR dvfs)
{
	G_advfs.DVFS = dvfs;
	//printf("G_advfs.DVFS = %x\n", G_advfs.DVFS);
	return D_DDIM_OK;
}

int Dd_PMC_ADVFS_Get_EN(UCHAR *const en)
{
	*en = G_advfs_en;
	return D_DDIM_OK;
}
int Dd_PMC_ADVFS_Get_Advfs(T_DD_PMC_ADVFS_DATA *const advfs)
{
	*advfs = G_advfs;
	return D_DDIM_OK;
}

